/***ExList By GYLite 2022-12-26
 * 扩展列表组件，支持列表项拖拽响应，键盘按键响应等
*/
class ExList extends GYLite.GYListV implements GYLite.IKeyBoardObject{
	protected _dragData:any;
	protected _dropData:any;
	protected _dropItem:GYLite.IItemRender;
	protected _dragHandle:GYLite.GYSprite;
	protected _dataCanDrag:boolean;
	public constructor(size: number, getGridFunc?: Function, getThisObject?: any, setGridFunc?: Function, setThisObject?: any) {
		super(size, getGridFunc, getThisObject, setGridFunc, setThisObject);
		let s= this;
		s.addEventListener(egret.Event.ADDED_TO_STAGE, s.addToStage, s);
		s.addEventListener(egret.Event.REMOVED_FROM_STAGE, s.removeFromStage, s);
	}
	private addToStage(e:egret.Event):void
	{
		let s = this;
		GYLite.GYKeyboard.getInstance().addKeyListener(s);
	}
	private removeFromStage(e:egret.Event):void
	{
		let s = this;
		GYLite.GYKeyboard.getInstance().removeKeyListener(s);
	}
	public get dataCanDrag():boolean
	{
		return this._dataCanDrag;
	}
	public set dataCanDrag(val:boolean)
	{
		this._dataCanDrag = val;
	}
	protected createDragShape(touchId:number,item:GYLite.GYSprite):GYLite.GYSprite
	{
		let sp:GYLite.GYImage;
		let g:egret.Graphics;
		let s = this;
		if(s._dragHandle == null)
		{
			s._dragHandle = new GYLite.GYImage;			
			sp = <any>s._dragHandle;
			sp.mouseThrough = true;
			sp.x = s.x + item.x;
			sp.y = s.y + item.y;
			let renderTexture:egret.RenderTexture;
			renderTexture = new egret.RenderTexture;
			renderTexture.drawToTexture(item);
			// g = sp.graphics;
			// g.clear();		
			// g.beginFill(0xffffff, 0.7);
			// g.drawRect(offsetX,offsetY,w,h);
			// g.endFill();
			sp.source = renderTexture;
			sp.alpha = 0.5;
			(<any>s.parent).addElement(sp);
			let drag:GYLite.DraggerHandle;
			drag = GYLite.DraggerHandle.getInstance(sp);
			drag.addBind(function(d:GYLite.DraggerHandle):void{
				let s =this;
				s._dragHandle.x = (<any>s._dragHandle.parent).mouseX - d.dragMouseX;
				s._dragHandle.y = (<any>s._dragHandle.parent).mouseY - d.dragMouseY;
			}, s);
			drag.startDrag(sp, touchId);
		}					
		return sp;
	}
	protected removeDragShape():void
	{
		let s = this;
		if(s._dragHandle)
		{
			GYLite.DraggerHandle.getInstance(s._dragHandle).clear();			
			(<egret.RenderTexture>(<GYLite.GYImage>s._dragHandle).source).dispose();
			(<GYLite.GYImage>s._dragHandle).source = null;
			s._dragHandle.dispose();
			s._dragHandle = null;
		}
	}
	protected getGrid():GYLite.IItemRender
	{var s = this;
		var item:GYLite.IItemRender;
		item = super.getGrid();		
		item.addEventListener(egret.TouchEvent.TOUCH_BEGIN, s.itemTouchBegin, s);
		item.addEventListener(egret.TouchEvent.TOUCH_END, s.itemTouchUp, s);	
		return item;
	}
	private itemTouchBegin(e:egret.TouchEvent):void
	{
		let s = this;
		if(s.dragSelect || s._canDrag)return;
		if(!s._dataCanDrag)return;		
		let item:GYLite.IItemRender = e.currentTarget;		
		s._dragData = e.currentTarget.getData();
		GYLite.GYSprite.addStageDown(item, s.itemtouchOutside, s);		
		s.addEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
		s.addEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);				
		let obj:ListDragData;
		let toX:number,toY:number;
		toX = item.mouseX;
		toY = item.mouseY;		
		obj = new ListDragData(s._dragData, null,toX,toY);
		if(s.hasEventListener(ListEvent.DRAG_START))					
			s.dispatchEventWith(ListEvent.DRAG_START, false, obj);
		if((<any>item).hasEventListener(ListEvent.DRAG_START))
			(<any>item).dispatchEventWith(ListEvent.DRAG_START, false, obj);		
	}
	private rollOut(e:egret.TouchEvent):void
	{
		let s = this;
		if(!s._dataCanDrag)return;
		s._dropData = null;
		if(s._dropItem)		
		{
			(<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false);
			s._dropItem = null;
		}
	}
	private itemtouchOutside(e:GYLite.GYTouchEvent):void
	{
		let s = this;
		if(!s._dataCanDrag)return;
		let tar:any;
		let toX:number,toY:number;
		let pr:any;
		let obj:ListDragData,obj2:ListDragData;
		pr = e.outsideTarget;
		while(pr && pr != GYLite.GYSprite.stage)
		{
			if(pr.receiveData && pr.receiveData.constructor == Function)
			{
				toX = pr.mouseX;
				toY = pr.mouseY;								
				obj2 = new ListDragData(s._dragData, null,toX,toY);
				if(tar == null)
				{
					tar = pr;
					obj = obj2;
				}
				pr.receiveData(obj2);				
			}
			pr = pr.parent;
		}		
		if(obj == null)
			obj = new ListDragData(s._dragData, null,toX,toY);
		if(s._dropItem)		
		{
			(<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);
			s._dropItem = null;
		}
		s._dragData = s._dropData = null;
		s.removeEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
		s.removeEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);
		s.removeDragShape();
	}
	private itemTouchUp(e:egret.TouchEvent):void
	{
		let s = this;
		if(!s._dataCanDrag)return;
		if(s.dragSelect || s._canDrag)return;
		let item:GYLite.IItemRender;
		let obj:ListDragData;
		let toX:number,toY:number;
		if(s._dragHandle)
		{
			item = e.currentTarget;		
			s._dropData = item.getData();		
			toX = item.mouseX;
			toY = item.mouseY;
			obj = new ListDragData(s._dragData, s._dropData,toX,toY);
			(<any>item).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);		
			if(s.hasEventListener(ListEvent.DROP))					
				s.dispatchEventWith(ListEvent.DROP, false, obj);
			if((<any>item).hasEventListener(ListEvent.DROP))
				(<any>item).dispatchEventWith(ListEvent.DROP, false, obj);
		}			
		
		s._dropItem = null;
		s.removeEventListener(GYLite.GYTouchEvent.TOUCH_MOVE, s.touchListMove, s);
		s.removeEventListener(GYLite.MouseEvent.ROLL_OUT, s.rollOut, s);
		s._dragData = s._dropData = null;
		s.removeDragShape();
	}
	private touchListMove(e:GYLite.GYTouchEvent):void
	{
		let s = this;
		if(!s._dataCanDrag)return;
		let item:GYLite.IItemRender;
		let pr:GYLite.GYSprite;
		let dropData:any;
		pr = e.target;
		while(pr && !GYLite.CommonUtil.GYIs(pr, GYLite.ItemRender))
		{			
			pr = <any>pr.parent;
		}
		if(pr == null)return;
		item = <any>pr;		
		s._dropData = item.getData();
		let obj:ListDragData;
		let toX:number,toY:number;
		toX = item.mouseX;
		toY = item.mouseY;
		obj = new ListDragData(s._dragData, s._dropData,toX,toY);
		if(s._dropItem && s._dropItem != item)		
			(<any>s._dropItem).dispatchEventWith(ListEvent.DRAG_OUT, false, obj);					
		s._dropItem = item;
		if(s.hasEventListener(ListEvent.DRAG_ENTER))					
			s.dispatchEventWith(ListEvent.DRAG_ENTER, false, obj);
		if((<any>item).hasEventListener(ListEvent.DRAG_ENTER))
			(<any>item).dispatchEventWith(ListEvent.DRAG_ENTER, false, obj);
		s.createDragShape(e.touchPointID, <any>item);
	}	
	///键盘操控
	public keyFocus(): boolean
	{
		return true;
	}
	public kDown(keyCode: number): void
	{let s =this;			
		let isCtrlDown:boolean,isAltDown:boolean;
		isCtrlDown = GYLite.GYKeyboard.getInstance().isCtrlDown();
		isAltDown = GYLite.GYKeyboard.getInstance().isAltDown();
		if(isCtrlDown)
		{
			if(keyCode == GYLite.Keyboard.A)
			{
				s.selectedData = s._dataProvider[s._dataProvider.length - 1];
				s.selectLine(s._dataProvider[0],s.selectedData,true);
			}
		}		
	}
	public kUp(keyCode: number): void
	{

	}
}
class ListEvent{
	/**列表项拖拽开始*/public static DRAG_START:string = "list_drag_start";
	/**列表项拖拽到外部，如果拖拽到非列表项上，会调用非列表项的receiveData方法以便传递数据*/public static DRAG_OUT:string = "list_drag_out";
	/**列表项拖拽进入其他列表项*/public static DRAG_ENTER:string = "list_drag_enter";
	/**列表项放置到其他列表项上*/public static DROP:string = "list_drop";
}
class ListDragData{
	/**拖拽的数据，列表项的数据**/public dragData:any;
	/**放置目标的数据，通常是另外一个列表项的数据**/public dropData:any;
	/**相对放置目标的放置坐标Y**/public offsetX:number;
	/**相对放置目标的放置坐标Y**/public offsetY:number;
	constructor(dragData:any, dropData:any=null, offsetX:number=0,offsetY:number=0){
		let s = this;
		s.dragData = dragData;
		s.dropData = dropData;
		s.offsetX = offsetX;
		s.offsetY = offsetY;
	}
}